import { Inject, Injectable } from '@nestjs/common';
import { DataSource, Equal, FindOptionsSelect, FindOptionsWhere, In, Repository } from 'typeorm';
import { plainToInstance } from 'class-transformer';
import {
  BaseRepository,
  indexPaginateBuilder,
  showBuilderEntity,
} from '@libs/common/repository';
import { ConstantEnum } from '@libs/common/enums';
import {
  Index{{ pascalCase name }}Dto,
  Create{{ pascalCase name }}Dto,
  Update{{ pascalCase name }}Dto,
  Show{{ pascalCase name }}Dto,
  Delete{{ pascalCase name }}Dto,
  Find{{ pascalCase name }}Dto,
} from './dto/{{ kebabCase name }}.dto';
import { {{ pascalCase name }} } from './entities/{{ kebabCase name }}.entity';
// import { ProviderKey } from './{{ kebabCase name }}.providers';

@Injectable()
export class {{ pascalCase name }}Service extends BaseRepository {
  // 普通操作数据库方式，如果使用到了事务，需要使用事务操作数据库方式
  // @Inject(ProviderKey)
  // private repository: Repository<{{ pascalCase name }}>;

  constructor(
    @Inject(ConstantEnum.DB_DATA_SOURCE_MANAGER) dataSource: DataSource,
  ) {
    super(dataSource);
  }

  protected repository = this.getRepository({{ pascalCase name }});

  protected repositoryManager = () => this.getRepository({{ pascalCase name }});

  // 需要再 .module 中注入
  // @Inject(XxxxService)
  // private xxxxService: XxxxService;

  async index(dto: Index{{ pascalCase name }}Dto) {
    const res = await indexPaginateBuilder({
      dto,
      repository: this.repository,
    });
    return res;
  }

  show<D extends Show{{ pascalCase name }}Dto = Show{{ pascalCase name }}Dto>(dto: D) {
    return showBuilderEntity(this.repository, dto);
  }

  /** 只返回一条对象数据，如果存在多个只返回第一条 */
  async findOne(dto: Find{{ pascalCase name }}Dto, select?: FindOptionsSelect<{{ pascalCase name }}>) {
    const entity = await this.findBase(dto);

    if (Array.isArray(entity) && entity.length > 0) {
      return entity[0];
    }

    return null;
  }

  /** 返回所有符合条件的数据 */
  find(dto: Find{{ pascalCase name }}Dto, select?: FindOptionsSelect<{{ pascalCase name }}>) {
    return this.findBase(dto);
  }

  private findBase(dto: Find{{ pascalCase name }}Dto, select?: FindOptionsSelect<{{ pascalCase name }}>) {
    const where: FindOptionsWhere<{{ pascalCase name }}> = {};
    // 更多 Find 条件查询
    if (dto.id) {
      where.id = dto.id;
    } else {
      return null;
    }

    return this.repository.find({ where });
  }

  async delete(dto: Delete{{ pascalCase name }}Dto) {
    const { id, ids } = dto;
    if (id) {
      await this.repositoryManager().delete({ id: Equal(id) });
    } else if (ids) {
      await this.repositoryManager().delete({ id: In(ids) });
    }
    return;
  }

  update(dto: Update{{ pascalCase name }}Dto | Update{{ pascalCase name }}Dto[]) {
    const dtos = Array.isArray(dto) ? dto : [dto];
    const entities = plainToInstance({{ pascalCase name }}, dtos);

    return this.repositoryManager().save(entities);
  }

  create(dto: Create{{ pascalCase name }}Dto | Create{{ pascalCase name }}Dto[]) {
    const entity = this.repositoryManager().create(plainToInstance({{ pascalCase name }}, dto));

    return this.repositoryManager().insert(entity);
  }

  import() {
    // CODE
  }

  export() {
    // CODE
  }

  switch(id: string, status: boolean) {
    // status 需要在 entity 中定义, 如果没有不需要这个接口
    // return this.repository.update({ id }, { status });
  }
}
